Обновление до dbt utils v1.0
Впервые dbt utils переходит на новую мажорную версию. Из публикации в блоге за прошлый месяц:
Пришло время официально закрепить то, что уже было негласным правилом: вы можете полагаться на dbt utils так же, как и на dbt v1, благодаря стабильным интерфейсам и последовательным, интуитивно понятным названиям.
Как и при переходе на dbt 1.0 в прошлом году, стандартизация и подготовка к будущему привели к некоторым несовместимым изменениям. Большинство изменений можно внести с помощью поиска и замены. Если вам нужна помощь, напишите на форуме сообщества или в канале #package-ecosystem в Slack.
Новые возможности
get_single_value()— Простой способ получить одно значение из SQL-запроса вместо обращения к элементу[0][0]результатаrun_query.safe_divide()— Возвращает null, когда знаменатель равен 0, вместо возникновения ошибки деления на ноль.- Новый тест
not_empty_string— Более простая обёртка для проверки длины значений в столбце, чем использованиеexpression_is_true.
Улучшения
- Многие тесты становятся более полезными, если запускать их для подгрупп строк таблицы. Например, может потребоваться проверить наличие свежих данных для каждого турникета, а не довольствоваться их наличием хотя бы для одного источника данных. Для этого добавьте в тесты новый аргумент
group_by_columns. Подробнее об этом читайте в статье, написанной автором теста. - Благодаря добавлению в макрос
star()аргументаquote_identifiers, включённого по умолчанию, теперь при необходимости можно отключить заключение идентификаторов в кавычки. - У теста
recencyтеперь есть необязательный аргументignore_time_component, который можно использовать при проверке столбца с датами. Это позволяет избежать ложноположительных и ложноотрицательных результатов, вызванных временем суток, в которое запускается тест.
Исправления
union()теперь включает и исключает столбцы без учёта регистраslugify()добавляет в начало символ подчёркивания, если первый символ — цифра- Тест
expression_is_trueбольше не выводит*, если сохранение не прошедших проверку строк не включено, что снижает затраты в BigQuery.
Несовместимые изменения
Изменения в surrogate_key():
surrogate_key()заменён наgenerate_surrogate_key(). Исходный макрос обрабатывал значения null и пустые строки одинаково, что могло приводить к созданию дублирующихся ключей. Уgenerate_surrogate_key()этого недостатка нет. Сравните суррогатные ключи, вычисленные для этих столбцов:
Изменение способа вычисления суррогатных ключей, даже в лучшую сторону, может иметь существенные последствия для их дальнейшего использования (например, в снимках и инкрементальных моделях, которые используют этот столбец в качестве unique_key). Поэтому можно включить прежнее поведение, задав следующую переменную в проекте dbt:
#dbt_project.yml
vars:
surrogate_key_treat_nulls_as_empty_strings: true #turn on legacy behavior
Создавая новый макрос вместо изменения поведения старого, мы требуем, чтобы во всех проектах, использующих этот макрос, было принято явное решение о том, какой подход лучше подходит для их задач.
Мы рекомендуем текущим пользователям включить прежнее поведение, если только вы не уверены в одном из следующих условий:
- ваши суррогатные ключи никогда не содержали null, или
- ваши суррогатные ключи не используются в инкрементальных моделях, снимках и других артефактах, сохраняющих состояние, и поэтому могут быть без проблем пересозданы с новыми значениями.
Нельзя рассчитывать на какое-либо одно поведение, поскольку каждый проект может настроить его по-своему.
Функциональность, теперь встроенная в dbt v1:
- У теста
expression_is_trueбольше нет отдельного аргументаcondition. Вместо него используйтеwhere, который теперь доступен во всех тестах на уровне ядра:
models:
- name: old_syntax
tests:
- dbt_utils.expression_is_true:
expression: "col_a + col_b = total"
#replace this...
condition: "created_at > '2018-12-31'"
- name: new_syntax
tests:
- dbt_utils.expression_is_true:
expression: "col_a + col_b = total"
# ...with this...
where: "created_at > '2018-12-31'"
Примечание — Из-за этого некоторые тесты могут получить одинаковые автоматически сгенерированные имена. Чтобы устранить проблему, можно задать собственное имя для теста.
- Устаревшие тесты
unique_whereиnot_null_whereудалены, поскольку where теперь доступен во всех тестах на уровне ядра. Для перехода найдите и заменитеdbt_utils.unique_whereнаunique, аdbt_utils.not_null_where— наnot_null. dbt_utils.current_timestamp()заменён наdbt.current_timestamp().- Обратите внимание, что реализация
dbt.current_timestamp()для Postgres и Snowflake отличается от прежней реализации вdbt_utils(подробности здесь). Если вы используете Postgres или Snowflake и вам нужно полностью сохранить прежнее поведение для обратной совместимости, используйтеdbt.current_timestamp_backcompat(). Мы надеемся устранить это расхождение в одной из будущих версий dbt.
- Обратите внимание, что реализация
- Все остальные кросс-платформенные макросы перенесены в пространство имён dbt; никаких изменений, кроме замены
dbt_utils.наdbt., не требуется. Полный список приведён в документации по кросс-платформенным макросам.- В редакторе кода можно выполнить глобальный поиск и замену с помощью регулярного выражения:
\{\{\s*dbt_utils\.(any_value|bool_or|cast_bool_to_text|concat|dateadd|datediff|date_trunc|escape_single_quotes|except|hash|intersect|last_day|length|listagg|position|replace|right|safe_cast|split_part|string_literal|type_bigint|type_float|type_int|type_numeric|type_string|type_timestamp|type_bigint|type_float|type_int|type_numeric|type_string|type_timestamp|except|intersect|concat|hash|length|position|replace|right|split_part|escape_single_quotes|string_literal|any_value|bool_or|listagg|cast_bool_to_text|safe_cast|dateadd|datediff|date_trunc|last_day)→{{ dbt.$1
- В редакторе кода можно выполнить глобальный поиск и замену с помощью регулярного выражения:
Удаление материализации insert_by_period
- Материализация
insert_by_periodперенесена в репозиторий experimental-features. Чтобы продолжить её использование, добавьте следующее в файл packages.yml:
packages:
- git: https://github.com/dbt-labs/dbt-labs-experimental-features
subdirectory: insert_by_period
revision: XXXX #optional but highly recommended. Provide a full git sha hash, e.g. 1c0bfacc49551b2e67d8579cf8ed459d68546e00. If not provided, uses the current HEAD.
Удаление устаревшего поведения:
safe_add()работает только со списком аргументов; используйте{{ dbt_utils.safe_add(['column_1', 'column_2']) }}вместо передачи отдельных аргументов{{ dbt_utils.safe_add('column_1', 'column_2') }}.- Реализован ряд давно обещанных изменений, связанных с удалением устаревших возможностей
deduplicate():- Аргумент
group_byзаменён наpartition_by. - Аргумент
relation_aliasудалён. Если нужен псевдоним, его можно передать непосредственно в аргументеrelation. - Аргумент
order_byтеперь обязателен. Передайте постоянное значение, например1, если вам неважно, каким образом удаляются дубликаты.
- Аргумент
- Устаревший аргумент
tableудалён изunpivot(). Вместо него используйтеrelation.
Устранение ошибок
Ниже приведены распространённые сообщения об ошибках, с которыми можно столкнуться после обновления, и способы их устранения.
dict object has no attribute MACRO_NAME
Причина: Макрос с именем MACRO_NAME не существует. Скорее всего, это связано с тем, что макрос перенесён в пространство имён dbt (см. выше). Также причиной может быть то, что вы не выполнили dbt deps или допустили опечатку в имени макроса.
Решение: Для кросс-платформенных макросов замените dbt_utils.MACRO_NAME() на dbt.MACRO_NAME().
macro 'dbt_macro__generate_surrogate_key' takes not more than 1 argument(s)
Причина: generate_surrogate_key() требует один аргумент, содержащий список столбцов, а не набор отдельных аргументов.
Решение: Замените вызов на dbt_utils.generate_surrogate_key(['column_1', 'column_2']) — обратите внимание на квадратные скобки.
The dbt_utils.surrogate_key has been replaced by dbt_utils.generate_surrogate_key
Причина: Макрос surrogate_key() был заменён.
Решение:
- Решите, нужно ли включить обратную совместимость, как описано выше.
- Найдите и замените
dbt_utils.surrogate_keyнаdbt_utils.generate_surrogate_key.
macro dbt_macro__test_expression_is_true takes no keyword argument condition
Причина: Аргумент condition удалён из теста expression_is_true, поскольку where теперь автоматически доступен для всех тестов.
Решение: Замените condition на where.
No materialization insert_by_period was found for adapter
Причина: Материализация insert_by_period перенесена в репозиторий экспериментальных возможностей (см. выше).
Решение: Установите пакет, как описано выше.
dbt found two tests with the name "XXX".
Причина: Замена condition на where в тесте expression_is_true, поскольку параметры конфигурации не входят в уникальное имя теста.
Решение: Задайте собственное имя для теста.
